//
// Created by 张闳 on 2021/12/3.
//

#include "strings.h"
#include <stdlib.h>
#include <string.h>

char* substr(char *str, int start, int length) {
    char *temp = str;
    int str_len = string_len(str);
    if (start >= str_len || start < 0 || length <= 0 || start + length >= str_len) {
        return (char*)NULL;
    } else {
        temp += start;
    }
    char *result = (char*)malloc(sizeof(char) * length);
    memset(result, 0, sizeof(char) * length);
    for (int i = 0; i < length; ++i) {
        *result = *temp;
        ++result;
        ++temp;
    }
    result -= length;
    return result;
}

char* substring(char *str, int start, int end) {
    char *temp = str;
    int str_len = string_len(str);
    if (start >= str_len || start < -str_len || end - start < 0) {
        return (char*)NULL;
    } else if (start < 0 && start >= -str_len) {
        temp += (str_len + start);
    } else {
        temp += start;
    }
    char *result = (char*)malloc(sizeof(char) * (end - start));
    memset(result, 0, sizeof(char) * (end - start));
    int i = start;
    for (; i < end; ++i) {
        *result = *temp;
        ++result;
        ++temp;
    }
    result -= (end - start);
    return result;
}

char* str_replace(char *str, char *search, char *replace) {
    int str_len = string_len(str);
    int search_len = string_len(search);
    int replace_len = string_len(replace);
    if (str_len < search_len) {
        return (char*)NULL;
    }
    int start = 0;
    char *result = create_string("");
    for (; start < str_len; ) {
        char *searched = substr(str, start, search_len);
        if (string_compare(searched, search) == true) {
            result = catenate_string(result, replace);
            if ((str_len - (start + search_len)) < search_len) {
                result = catenate_string(result, substr(str, start + search_len, str_len - (start + search_len)));
                break;
            }
            start += search_len;
        } else {
            char c = str[start];
            char *temp = (char*)malloc(sizeof(char*) * 2);
            memset(temp, 0, sizeof(char*) * 2);
            *temp = c;
            result = catenate_string(result, temp);
            ++start;
        }
    }
    return result;
}

bool string_compare(char *str1, char *str2) {
    char *temp1 = str1, *temp2 = str2;
    int str1_len = string_len(temp1);
    int str2_len = string_len(temp2);
    if (str1_len != str2_len) {
        return false;
    } else {
        while (*temp1) {
            if (*temp1 != *temp2) {
                return false;
            }
            ++temp1;
            ++temp2;
        }
        return true;
    }
}

char* create_string(char *str) {
    int len = string_len(str);
    char* s = (char*)malloc(sizeof(char) * (len + 1));
    memset(s, 0, sizeof(char) * (len + 1));
    if (s != NULL) {
        if (len > 0) {
            strcpy(s, str);
        } else {
            strcpy(s, "");
        }
    }
    return s;
}

char *clone_string(char *str) {
    int len = string_len(str);
    char *s = (char *) malloc(len + 1);
    memset(s, 0, sizeof(char) * (len + 1));
    char *p = str;
    char *ps = s;
    for (int i = 0; i < len; i++) {
        *ps = *p;
        p++;
        ps++;
    }
    return s;
}


char *catenate_string(char *str1, char *str2) {
    int str1_len = string_len(str1), str2_len = string_len(str2);
    if (str1_len == 0 && str2_len == 0) {
        return (char *) NULL;
    }
    int len = str1_len + str2_len;
    char *s = (char *) malloc(sizeof(char) * (len + 1));
    memset(s, 0, sizeof(char) * (len + 1));
    if (s != NULL) {
        if (str1_len > 0 && str2_len > 0) {
            strcpy(s, str1);
            strcat(s, str2);
        } else if (str1_len > 0 && str2_len == 0) {
            strcpy(s, str1);
        } else if (str1_len == 0 && str2_len > 0) {
            strcpy(s, str2);
        }
    }
    return s;
}

int string_len(char* str) {
    char* temp = str;
    if (temp == (char*)NULL) {
        return 0;
    }
    int len = 0;
    while (*temp) {
        ++len;
        ++temp;
    }
    return len;
}

bool has_headtail_space(char *str) {
    char *temp = str;
    int temp_len = string_len(temp);
    while (*temp) {
        if (*temp == ' ') {
            return true;
        } else {
            break;
        }
        ++temp;
    }
    while (*temp) {
        ++temp;
    }
    --temp;
    while (*temp) {
        if (*temp == ' ') {
            return true;
        } else {
            break;
        }
        --temp;
    }
    return false;
}

char* trim_string(char *str) {
    char *temp = str, *temp_c = (char*)malloc(sizeof(char) * 2);
    int temp_len = string_len(temp);
    char *result = (char*)malloc(sizeof(char) * temp_len);
    char c;
    memset(result, 0, sizeof(char) * temp_len);
    memset(temp_c, 0, sizeof(char) * 2);
    bool is_left = false, is_right = false;
    while (*temp) {
        c = *temp;
        if (c == ' ' && !is_left) {
            ++temp;
            continue;
        }
        *temp_c = c;
        strcat(result, temp_c);
        ++temp;
        if (!is_left) {
            is_left = true;
        }
    }
    --temp;
    int right_index = 0;
    while (*temp) {
        c = *temp;
        if (c == ' ') {
            ++right_index;
        } else {
            break;
        }
        --temp;
    }
    result = substr(result, 0, string_len(result) - right_index);
    return result;
}

char* get_visible_string(char *str) {
    char *temp = str;
    char *result = (char*)malloc(sizeof(char) * (string_len(temp) + 1));
    char *t = (char*)malloc(sizeof(char) * 2);
    memset(result, 0, sizeof(char) * (string_len(str) + 1));
    memset(t, 0, sizeof(char) * 2);
    strcpy(result, "");
    strcpy(t, "");
    while (*temp) {
        char c = *temp;
        if (c >= (char)33 && c <= (char)126) {
            *t = c;
            strcat(result, t);
        }
        ++temp;
    }
    free(t);
    return result;
}

void* destroy_string(char* str) {
    if (str != NULL) {
        free(str);
    }
    return NULL;
}

char** string_sort_bylength(int array_length, char **source) {
    int i = 0, j;
    for (; i < array_length - 1; ++i) {
        for (j = 0; j < array_length - 1 - i; ++j) {
            if (string_len(source[j]) < string_len(source[j + 1])) {
                char *temp = source[j];
                source[j] = source[j + 1];
                source[j + 1] = temp;
            }
        }
    }
    return source;
}

char* get_strings_head(int str_count, char **strs) {
    char *s = (char*)NULL;
    char *temp = (char*)malloc(sizeof(char) * 2);
    memset(temp, 0, sizeof(char) * 2);
    int i = 0;
    for (; i < str_count; ++i) {
        *temp = *(strs[i]);
        s = catenate_string(s, temp);
    }
    return s;
}


bool is_letter_start(char *s) {
    if (string_len(s) == 0) {
        return false;
    }
    if ((*s >= 'a' && *s <= 'z') ||
        (*s >= 'A' && *s <= 'Z')) {
        return true;
    } else {
        return false;
    }
}

bool is_underline_start(char *s) {
    if (string_len(s) == 0) {
        return false;
    }
    if (*s == '_') {
        return true;
    } else {
        return false;
    }
}

bool is_sth_start(char *s, char start) {
    if (string_len(s) == 0) {
        return false;
    }
    if (*s == start) {
        return true;
    } else {
        return false;
    }
}

bool in_words_array(char **array, int array_length, char *search) {
    int i = 0;
    for (; i < array_length; ++i) {
        if (string_compare(array[i], search)) {
            return true;
        }
    }
    return false;
}

bool in_words_array_ex(char **array, int array_length, char *search, int index, int *len_pointer) {
    int i = 0;
    for (; i < array_length; ++i) {
        int array_index_len = string_len(array[i]);
        if (string_compare(array[i], substr(search, index, array_index_len))) {
            *len_pointer = array_index_len;
            return true;
        }
    }
    return false;
}

bool in_string(char *str, char search) {
    char *temp = str;
    while (*temp) {
        if (*temp == search) {
            return true;
        }
        ++temp;
    }
    return false;
}

bool start_with(char *str, char *start){
    if (str == NULL || *str == '\0') {
        return false;
    }
    int len = string_len(start);
    int len_str = string_len(str);
    if (len_str < len) {
        return false;
    }
    char *s1=str;
    char *s2=start;
    for (int i = 0; i < len;i++){
        if (*s1 != *s2) {
            return false;
        }
        s1++;
        s2++;
    }
    return true;
}
bool end_with(char *str, char *end){
    if (str == NULL || *str == '\0') {
        return false;
    }
    int len = string_len(end);
    int len_str = string_len(str);
    if (len_str < len) {
        return false;
    }
    char *s1=str+len_str;
    char *s2=end+len;
    for (int i = 0; i < len;i++){
        if (*s1 != *s2) {
            return false;
        }
        s1--;
        s2--;
    }
    return true;
}
